条件编译

  有一种宏的使用几乎不可能避免。指令#ifdef identifier将条件性地导致随后的输入被忽略,直到遇到一个#endif指令。例如,

    int f(int a
    #ifdef arg_two
        , int b
    #endif
    );

产生

    int f(int a
    );

给编译器去看,除非名为arg_two的宏义已经用#define定义。这种例子会把工具弄糊涂,而程序员通常总认为它们的行为是合理的。

  #ifdef的大部分使用没有这么古怪。有节制地使用#ifdef不会有什么害处。另见9.3.3节。

  用于控制#ifdef的名字应该仔细选择,使之不会与正常的标识符相冲突。例如,

    struct Call_info {
        Node* arg_one;
        Node* arg_two;
        // ...
    };

这样看起来很清白的代码也可能产生混乱,假如某人写了:

#define arg_two x

不幸的是,普通的、无法避免的头文件里包含着许多危险且毫无必要的宏。

🔚